'use strict'

angular.module('pl.menu', ['underscore', 'pl.utils'])
	.controller('plMenuCtrl', ['$scope', '$attrs', '$plUtils', function ($scope, $attrs, $plUtils) {
		console.log('plMenuCtrl $scope.$id:' + $scope.$id);

		this.settings = {
			openAtSameTime: false
		}

		var defaultValues = {
			active: false,
		}

		_.extend($scope.menus, {id: 0})

		parseSubmenu(0, $scope.menus, 0);

		/*
			Action Methods
		*/

		function parseSubmenu (parentId, submenus, level) {
			_.each(submenus, function(submenu, ind){
				_.extend(submenu, defaultValues);
				submenu.parentId = parentId;
				submenu.level = level;
				if (!submenu.id) {
					submenu.id = $plUtils.uuid(8, 16);
				}

				var submenuArray = submenu.submenu;
				if (submenuArray) {
					if (submenuArray instanceof Array && submenuArray.length > 0) {
						submenuArray.isOpen = submenu.active;
						parseSubmenu(submenu.id, submenuArray, level + 1);
					} else {
						delete submenu['submenu'];
					}
				}
			})
		}

		this.hasSubmenu = function (menu) {
			if (!menu || !menu.submenu) {
				return false;
			}

			if (menu.submenu instanceof Array && menu.submenu.length > 0) {
				return true;
			}

			return false;
		}

		this.getMenus = function () {
			return $scope.menus;
		}

		this.getMenuItemById = function (id) {
			var self = this;
			var menus = $scope.menus;
			var rst;

			function find (menus){
				_.each(menus, function (menu) {
					if (menu.id == id) {
						rst = menu;
						return;
					} else {
						if (self.hasSubmenu(menu)) {
							rst = find(menu.submenu);
						}
					}
				})
				return rst;
			}

			rst = (id == 0)? menus : find(menus);

			return rst
		}

		this.getBrothersMenuItemByParentId = function (parentId) {
			var p = this.getMenuItemById(parentId);

			switch(parentId){
				case 0: return p;
				default: return p.submenu;
			}
		}

		/*
			Event Handlers
		*/

		var self = this;

		this.activeMenuItem = function (item, itemScope) {
			item.active = true;

			if (self.hasSubmenu(item) && itemScope) {
				itemScope.$broadcast('pl.menu.open.submenu', item.id);
			}
		}

		this.inactiveMenuItem = function (item, itemScope) {
			item.active = false;

			if (self.hasSubmenu(item) && itemScope) {
				itemScope.$broadcast('pl.menu.close.submenu');
			}
		}

		this.menuItemOnClick = function (itemScope) {
			var item = itemScope.item;
			if (self.hasSubmenu(item)) {
				self.toggleMenuItemActive(itemScope.item, itemScope);
			} else {
				self.activeMenuItem(item);
			}
			$scope.$broadcast('pl.menu.inactive.others.menuitem', item.parentId, item.id);
		}

		this.toggleMenuItemActive = function (item, itemScope) {
			item.active = !item.active;
			if (itemScope) {
				(item.active)? itemScope.$broadcast('pl.menu.open.submenu', item.id) : itemScope.$broadcast('pl.menu.close.submenu');
			}
		}

		this.openSubmenu = function (event, pid) {
			var submenuScope = event.currentScope;
			if (submenuScope.pid == pid) {
				submenuScope.menus.isOpen = true;
			}
		}

		this.closeSubmenu = function (event) {
			var submenuScope = event.currentScope;
			submenuScope.menus.isOpen = false;
			submenuScope.$emit('pl.menu.inactive.submenu.parent.menuitem', submenuScope.pid);
		}

		this.inactiveSubmenuParentMenuItem = function (event, pid) {
			var item = event.currentScope.item;
			if (item.id == pid) {
				self.inactiveMenuItem(item);
			}
		}

		this.inactiveOthersMenuItem = function (event, parentId, selfId) {
			var item = event.currentScope.item;
			var itemScope = (self.settings.openAtSameTime)? event.currentScope : undefined;
			if (item.id != selfId && item.id != parentId) {
				self.inactiveMenuItem(item, itemScope);
			}
		}
	}])
	.directive('plMenu', function () {
		
		return {
			restrict: 'E',
			replace: true,
			controller: 'plMenuCtrl',
			scope: {
				menus: '=',
			},
			templateUrl: 'pl/menu/menu.tmpl.html',
			link: function ($scope, $elm, $attrs, controller) {
				console.log('plMenu $scope.$id:' + $scope.$id);
			}
		}
	})
	.directive('plSubmenu', function () {

		return {
			restrict: 'E',
			replace: true,
			require: '^plMenu',
			scope: {
				menus: '=',
				pid: '='
			},
			templateUrl: 'pl/menu/submenu.tmpl.html',
			compile: function ($elm, $attrs, $transcludeFn) {
				return {
					post: function ($scope, $elm, $attrs, controller, linker) {
						$scope.hasSubmenu = controller.hasSubmenu;
						
						$scope.$on('pl.menu.open.submenu', controller.openSubmenu);

						$scope.$on('pl.menu.close.submenu', controller.closeSubmenu);
					}
				} 
			}
		}
	})
	.directive('plMenuItem', function () {
		return {
			restrict: 'E',
			replace: true,
			require: '^plMenu',
			templateUrl: 'pl/menu/menuItem.tmpl.html',
			compile: function ($elm, $attrs, $transcludeFn) {
				return {
					post: function ($scope, $elm, $attrs, controller, linker) {
						console.log('plMenuItem postLink');
						$scope.hasSubmenu = controller.hasSubmenu;
						
						$scope.toggleActive = controller.menuItemOnClick;

						$scope.$on('pl.menu.inactive.submenu.parent.menuitem', controller.inactiveSubmenuParentMenuItem);

						$scope.$on('pl.menu.inactive.others.menuitem', controller.inactiveOthersMenuItem);
					}
				} 
			}
		}
	})
	.run(['$templateCache', function($templateCache){
		$templateCache.put('pl/menu/menu.tmpl.html', 
			 '<ul class="sidebar-menu">' + 
				'<pl-menu-item ng-repeat="item in menus" item="item"></pl-menu-item>' +
		     '</ul>'
		);

		$templateCache.put('pl/menu/submenu.tmpl.html', 
			 '<ul class="sidebar-menu" ng-show="menus.isOpen">' + 
				'<pl-menu-item ng-repeat="item in menus" item="item"></pl-menu-item>' +
		     '</ul>'
		);

		$templateCache.put('pl/menu/menuItem.tmpl.html', 
			'<li class="sidebar-menu-item">' +
	            '<a ui-sref="{{item.href}}" ng-class="{true: \'active\', false: \'\'}[item.active]" ng-click="toggleActive(this)"><i class="{{item.icon}}"></i><span ng-bind="item.text"></span><span class="sidebar-menu-arrow" ng-if="hasSubmenu(item)"><i class="glyphicon glyphicon-menu-down"></i></span></a>' +
	        	'<pl-submenu ng-if="hasSubmenu(item)" menus="item.submenu" pid="item.id"></pl-menu>' +
	        '</li>'
		);
	}])
